import { Context, Next } from 'koa'
import jwt from 'jsonwebtoken'
import { createError } from './errorHandler'

export interface JwtPayload {
    userId: string
    email: string
    username: string
}

declare module 'koa' {
    interface DefaultContext {
        user?: JwtPayload
    }
}

// 需要认证的路由路径
const protectedPaths = [
    '/api/users/profile',
    '/api/posts/create',
    '/api/posts/update',
    '/api/posts/delete',
    '/api/comments/create',
    '/api/comments/update',
    '/api/comments/delete'
]

// 检查路径是否需要认证
function isProtectedPath(path: string): boolean {
    return protectedPaths.some(protectedPath => path.startsWith(protectedPath))
}

export const authMiddleware = async (ctx: Context, next: Next) => {
    // 如果不是受保护的路径，直接继续
    if (!isProtectedPath(ctx.path)) {
        return await next()
    }

    try {
        // 获取 token
        const authHeader = ctx.headers.authorization
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
            throw createError.unauthorized('No token provided')
        }

        const token = authHeader.substring(7) // 移除 "Bearer " 前缀

        // 验证 token
        const jwtSecret = process.env.JWT_SECRET
        if (!jwtSecret) {
            throw new Error('JWT_SECRET is not configured')
        }

        const decoded = jwt.verify(token, jwtSecret) as JwtPayload
        ctx.user = decoded

        await next()
    } catch (error: any) {
        if (error.name === 'JsonWebTokenError') {
            throw createError.unauthorized('Invalid token')
        }
        if (error.name === 'TokenExpiredError') {
            throw createError.unauthorized('Token expired')
        }
        throw error
    }
}

// 生成 JWT token
export function generateToken(payload: JwtPayload): string {
    const jwtSecret = process.env.JWT_SECRET
    const expiresIn = process.env.JWT_EXPIRES_IN || '7d'

    if (!jwtSecret) {
        throw new Error('JWT_SECRET is not configured')
    }

    return jwt.sign(payload, jwtSecret, { expiresIn })
}

// 验证 token（用于手动验证）
export function verifyToken(token: string): JwtPayload {
    const jwtSecret = process.env.JWT_SECRET
    if (!jwtSecret) {
        throw new Error('JWT_SECRET is not configured')
    }

    return jwt.verify(token, jwtSecret) as JwtPayload
}
